package com.stars.easyms.schedule.util;

import com.stars.easyms.schedule.enums.DbType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 包路径相关工具类
 *
 * @author guoguifang
 */
public class DistributedSchedulePackageUtil {

    private static final Logger logger = LoggerFactory.getLogger(DistributedSchedulePackageUtil.class);

    private static String rootPackageName;

    private static DbType dbType;

    private static String repositoryPackageName;

    private static String repositoryClassName;

    private static Boolean allowBatch;

    private static ReentrantLock mainLock = new ReentrantLock();

    /**
     * 获取分布式调度框架的根路径
     */
    public static String getRootPackageName() {
        if (rootPackageName == null) {
            mainLock.lock();
            try {
                if (rootPackageName == null) {
                    String currentPackage = DistributedSchedulePackageUtil.class.getPackage().getName();
                    rootPackageName = currentPackage.substring(0, currentPackage.lastIndexOf("."));
                }
            } finally {
                mainLock.unlock();
            }
        }
        return rootPackageName;
    }

    /**
     * 获取存放持久化仓库包的路径
     */
    public static String getRepositoryPackageName() {
        if (repositoryPackageName == null) {
            mainLock.lock();
            try {
                if (repositoryPackageName == null) {
                    repositoryPackageName = getRootPackageName() + ".repository." + getDbType().getName();
                }
            } finally {
                mainLock.unlock();
            }
        }
        return repositoryPackageName;
    }

    /**
     * 获取存放持久化仓库类的路径
     */
    public static String getRepositoryClassName() {
        if (repositoryClassName == null) {
            mainLock.lock();
            try {
                if (repositoryClassName == null) {
                    repositoryClassName = getRepositoryPackageName() + "." + StringUtils.capitalize(getDbType().getName()) + "DistributedScheduleDAO";
                }
            } finally {
                mainLock.unlock();
            }
        }
        return repositoryClassName;
    }

    /**
     * 获取当前数据库类型，若获取失败则为致命错误直接关闭服务
     */
    public static DbType getDbType() {
        if (dbType == null) {
            mainLock.lock();
            try {
                if (dbType == null) {
                    String mysqlBatchParam = "rewriteBatchedStatements";
                    Connection conn = null;
                    try {
                        conn = ApplicationContextHolder.getApplicationContext().getBean(DataSource.class).getConnection();
                        DatabaseMetaData databaseMetaData = conn.getMetaData();
                        String driverName = databaseMetaData.getDriverName().toLowerCase();
                        dbType = driverName.contains(DbType.ORACLE.getName()) ? DbType.ORACLE : DbType.MYSQL;
                        if (DbType.ORACLE == dbType) {
                            allowBatch = Boolean.TRUE;
                        } else {
                            String url = databaseMetaData.getURL();
                            if (url.contains(mysqlBatchParam)) {
                                int batchParamIndex = url.lastIndexOf(mysqlBatchParam) + mysqlBatchParam.length() + 1;
                                int ampersandIndex = url.indexOf("&", batchParamIndex);
                                allowBatch = ampersandIndex != -1 ? Boolean.valueOf(url.substring(batchParamIndex, ampersandIndex).trim()) : Boolean.valueOf(url.substring(batchParamIndex).trim());
                            } else {
                                allowBatch = Boolean.FALSE;
                            }
                        }
                        if (!allowBatch) {
                            logger.warn("Please add the parameter '{}' to the dataSource URL and set it to true, otherwise batch operation cannot be used.", mysqlBatchParam);
                        }
                    } catch (Exception e) {
                        logger.error("Get dataSource connection failure!", e);
                        System.exit(1);
                    } finally {
                        if (conn != null) {
                            try {
                                conn.close();
                            } catch (SQLException e) {
                                //ignore
                            }
                        }
                    }
                }
            } finally {
                mainLock.unlock();
            }
        }
        return dbType;
    }

    /**
     * 获取当前数据库连接是否允许批量操作
     */
    public static boolean isAllowBatch() {
        if (allowBatch == null) {
            getDbType();
        }
        return allowBatch;
    }
}
